package com.coder.rental.security;

import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author: zhanglin
 * @description:   SpringSecurity配置类
 * @date 2025/3/24
 */
@Configuration
@EnableWebSecurity   //启动SpringSecurity的web安全功能，比如过滤器链
public class SecurityConfig {
    /*
    * @Resource是依据名称进行依赖注入，可避免多个同类型的Bean
    * @Autowired是依据类型进行依赖注入，会出现多个同类型的Bean
    * */
    @Resource
    private LoginSuccessHandler loginSuccessHandler;//登录成功处理器
    @Resource
    private LoginFailHandler loginFailHandler;//登录失败处理器
    @Resource
    private CustomerAccessDeniedHandler customerAccessDeniedHandler;//用户无权访问处理器
    @Resource
    private CustomerAnonymousEntryPoint customerAnonymousEntryPoint;//匿名无权访问处理器
    @Resource
    private CustomerUserDetailsService customerUserDetailsService;//用户详情服务
    @Resource
    private VerifyTokenFilter verifyTokenFilter;//token校验
    /*
    * 配置安全过滤器链
    * http 用户配置HttpSecurity的接口
    * Exception 如果配置过程中发生错误，则抛出异常
    * */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
        //登录前过滤配置
        http.addFilterBefore(verifyTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //SpringSecurity过滤器链
        http.formLogin()
                .loginProcessingUrl("/rental/user/login")//设置登录处理URL
                .successHandler(loginSuccessHandler)     //设置登录成功处理器
                .failureHandler(loginFailHandler)        //失败
                .and() //继续配置过滤
                .sessionManagement()//设置会话管理
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)//设置会话创建策略为无状态
                .and()
                .authorizeHttpRequests()//授权请求配置
                .requestMatchers("/rental/user/login")//匹配登录请求
                .permitAll()//允许访问所有请求访问
                .anyRequest().authenticated() //任何其他请求需要认证
                .and()
                .exceptionHandling()//异常处理配置
                .authenticationEntryPoint(customerAnonymousEntryPoint)//匿名无权访问
                .accessDeniedHandler(customerAccessDeniedHandler)//用户无权访问
                .and()
                .cors()//跨域配置
                .and()
                .csrf().disable()//关闭CSRF保护，CRSF是跨域请求伪造，CRSF会给每个跨域请求颁发CRSF令牌以限制跨域请求，关闭则不进行CRSF令牌验证。
                .userDetailsService(customerUserDetailsService);//配置用户详情服务
        return http.build();//构建并返回安全过滤器链
    }
}
